﻿using System.Windows.Controls;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Tequila.AugmentedReality.Data;
using Matrix = Microsoft.Xna.Framework.Matrix;

namespace Tequila.AugmentedReality.CameraStates
{
    internal abstract class CameraBaseState
    {
        // NOTE: The potential field of view of device's camera. It is may be wrong, because first time's result of calculating camera's field of view
        //       gave us 64 degrees (1.12 radians). If we suggest that compass works fine, the augmented reality is very wrong. Combining & finding
        //       some magic number gave us this value, but we're not exactly sure, that it's correct. But there's one reason, that says iphone's camera
        //       has the same field of view. And finally, the compass works synchronously with AR if we use this valuew.
        private const float FieldOfView = 0.8f;
        
        protected Matrix Projection;
        protected Matrix View;
        protected Viewport Viewport;

        protected CameraBaseState(int layoutWidth, int layoutHeight, int radius)
        {
            Viewport = new Viewport(0, 0, layoutWidth, layoutHeight);
            Projection = Matrix.CreatePerspectiveFieldOfView(FieldOfView, Viewport.AspectRatio, 1, radius);
        }

        public bool IsInitialized
        {
            get;
            protected set;
        }

        public bool ViewportIsZero
        {
            get
            {
                return Viewport.Width == 0;
            }
        }

        public void UpdatePlacePosition(CameraPoi placeIcon, Vector3 placeVector, Matrix rotation)
        {
            var projected = ProjectPlacePosition(rotation, placeVector);

            if (IsNotVisible(projected) || !IsVectorValid(projected))
            {
                placeIcon.IsVisible = false;
            }
            else
            {
                placeIcon.ZIndex = short.MaxValue - (int)placeVector.Length();
                
                placeIcon.X = projected.X;
                placeIcon.Y = projected.Y;

                placeIcon.IsVisible = true;
            }

        }

        private static bool IsNotVisible(Vector3 projected)
        {
            return projected.Z > 1 || projected.Z < 0;
        }

        public void Initialize()
        {
            if (IsInitialized)
            {
                return;
            }

            SetCameraView();
            IsInitialized = true;
        }

        protected abstract void SetCameraView();
        protected abstract Vector3 ProjectPlacePosition(Matrix rotation, Vector3 placeVector);

        protected Matrix ConvertRotationToXNACoordinates(Matrix rotation)
        {
            return Matrix.CreateRotationX(MathHelper.PiOver2) * rotation;
        }

        protected Vector3 ProjectVectorToScreenCoordinates(Matrix attitude, Matrix world)
        {
            return Viewport.Project(Vector3.Zero, Projection, View, world * attitude);
        }

        //protected void Move(PointOfInterestControl icon, Vector3 vector)
        //{
        //    if (!IsVectorValid(vector))
        //    {
        //        return;
        //    }

        //    var storyboard = new Storyboard();
            
        //    const int duration = 250;

        //    var moveByXAnimation = new DoubleAnimation
        //    {
        //        From = icon.Moving.X,
        //        To = vector.X - (icon.RenderSize.Width / 2),
        //        Duration = TimeSpan.FromMilliseconds(duration),
        //    };

        //    Storyboard.SetTarget(moveByXAnimation, icon.Moving);
        //    Storyboard.SetTargetProperty(moveByXAnimation, new PropertyPath(TranslateTransform.XProperty));
        //    storyboard.Children.Add(moveByXAnimation);
            
        //    var moveByYAnimation = new DoubleAnimation
        //    {
        //        From = icon.Moving.Y,
        //        To = vector.Y - (icon.RenderSize.Height / 2),
        //        Duration = TimeSpan.FromMilliseconds(duration)
        //    };


        //    Storyboard.SetTarget(moveByYAnimation, icon.Moving);
        //    Storyboard.SetTargetProperty(moveByYAnimation, new PropertyPath(TranslateTransform.YProperty));
        //    storyboard.Children.Add(moveByYAnimation);
        //    storyboard.Begin();

        //}

        //private static void SetPosition(PointOfInterestControl placeIcon, Vector3 projected)
        //{
        //    placeIcon.Moving.X = projected.X - (placeIcon.RenderSize.Width / 2);
        //    placeIcon.Moving.Y = projected.Y - (placeIcon.RenderSize.Height / 2);  
        //}

        private static bool IsVectorValid(Vector3 vector)
        {
            return !double.IsNaN(vector.X) && !double.IsNaN(vector.Y) && !double.IsNaN(vector.Z);
        }
    }
}
